package com.cooper.mediadb;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import com.cooper.android.comm.ReflectionUtils;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public abstract class BaseMediaDataDao implements Mark.MarkDao {

	protected abstract SQLiteOpenHelper getDataHelper();

	protected void execSqls(final List<String> sqls) {
		SQLiteDatabase db = getDataHelper().getWritableDatabase();
		try {
			db.beginTransaction();
			try {
				for (String sql : sqls) {
					db.execSQL(sql);
				}
				db.setTransactionSuccessful();
			} finally {
				db.endTransaction();
			}
		} finally {
			db.close();
		}
	}

	protected String sqlTextValue(String value) {
		if (value != null) {
			return "\'" + value.replace("'", "''") + "\'";
		} else
			return null;
	}

	protected <T extends Media> void fillMediaInfo(T media, Cursor cursor) {
		for (int i = 0; i < cursor.getColumnCount(); i++) {
			Object param;
			if ("JOIN_TIME".equals(cursor.getColumnName(i))) {
				param = new Date(cursor.getLong(i));
			} else
				param = cursor.getString(i) == null ? "" : cursor.getString(i);
			try {
				media.getClass()
						.getMethod(
								ReflectionUtils.fieldToJavaSet(cursor
										.getColumnName(i)),
								new Class[] { param.getClass() })
						.invoke(media, new Object[] { param });
			} catch (SecurityException e) {
				Log.e("MediaDB", e.getMessage(), e);
			} catch (NoSuchMethodException e) {
				Log.e("MediaDB", e.getMessage(), e);
			} catch (IllegalArgumentException e) {
				Log.e("MediaDB", e.getMessage(), e);
			} catch (IllegalAccessException e) {
				Log.e("MediaDB", e.getMessage(), e);
			} catch (InvocationTargetException e) {
				Log.e("MediaDB", e.getMessage(), e);
			}
		}
	}

	@Override
	public synchronized Mark getMark(String mediaId) {
		SQLiteDatabase db = getDataHelper().getReadableDatabase();
		try {
			Cursor cursor = db.rawQuery(
					"SELECT TYPE,LAST_URI,LAST_POSITION FROM MEDIA_MARK"
							+ " WHERE MOVIE_ID =?", new String[] { mediaId });
			if (cursor != null)
				try {
					if (cursor.moveToFirst()) {
						return new Mark(mediaId, cursor.getInt(0),
								cursor.getString(1), cursor.getInt(2));
					}
				} finally {
					cursor.close();
				}
			return null;
		} finally {
			db.close();
		}
	}

	@Override
	public void insertMark(final String mediaId, final int type,
			final String uri, final int position) {

		new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized (BaseMediaDataDao.this) {
					SQLiteDatabase db = getDataHelper().getWritableDatabase();
					try {
						db.beginTransaction();
						try {
							db.execSQL(
									"DELETE FROM MEDIA_MARK WHERE MOVIE_ID=?",
									new String[] { mediaId });
							db.execSQL(
									"INSERT INTO MEDIA_MARK(MOVIE_ID,TYPE,LAST_URI,LAST_POSITION) VALUES(?,?,?,?)",
									new String[] { mediaId,
											String.valueOf(type), uri,
											String.valueOf(position) });
							db.setTransactionSuccessful();
						} finally {
							db.endTransaction();
						}
					} finally {
						db.close();
					}
				}
			}
		}).start();
	}

	public synchronized boolean tableIsExists(String table) {
		SQLiteDatabase db = getDataHelper().getReadableDatabase();
		try {
			Cursor cursor = db
					.rawQuery(
							"select sql from sqlite_master where tbl_name=? and type='table'",
							new String[] { table.toUpperCase() });
			if (cursor != null)
				try {
					return cursor.getCount() > 0;
				} finally {
					cursor.close();
				}
			else
				return false;
		} finally {
			db.close();
		}
	}

	public synchronized boolean fieldIsExists(String table, String field) {

		if ((field != null) && !"".equals(field)) {
			SQLiteDatabase db = getDataHelper().getReadableDatabase();
			try {
				Cursor cursor = db
						.rawQuery(
								"select sql from sqlite_master where tbl_name=? and type='table'",
								new String[] { table.toUpperCase() });
				if (cursor != null)
					try {
						if (cursor.moveToFirst()) {
							Pattern pSplit = Pattern
									.compile("\\s[^;]+?,\\s*|^[^;]*?\\(\\s*|\\s[^;]*?\\)\\W*?$");
							return Arrays.asList(
									pSplit.split(cursor.getString(0)))
									.contains(field.toUpperCase());
						}
					} finally {
						cursor.close();
					}
			} finally {
				db.close();
			}
		}
		return false;
	}

}
